package net.xxcxcxcx.xc_enhancedmob.render.particle.custom;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.particle.*;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.particle.DefaultParticleType;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Quaternion;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3f;

import java.util.Random;

//这是一个永远指向玩家方向的粒子，因为指向玩家所以渲染可以只有一面
@Environment(value = EnvType.CLIENT)
public class CustomBaseParticle extends SpriteBillboardParticle {
    public static Random random = new Random();
    public final SpriteProvider spriteProvider;
    private float anglespeed;

    public CustomBaseParticle(SpriteProvider spriteProvider, ClientWorld world, double x, double y, double z) {
        this(spriteProvider, world, x, y, z, 0, 0, 0);
    }

    public CustomBaseParticle(SpriteProvider spriteProvider, ClientWorld world, double x, double y, double z,
                              double velocityX, double velocityY, double velocityZ) {
        this(spriteProvider, world, x, y, z, velocityX, velocityY, velocityZ, 0, 1, 20, 1, 1, 1, 1);
    }

    public CustomBaseParticle(SpriteProvider spriteProvider, ClientWorld world, double x, double y, double z,
                              double velocityX, double velocityY, double velocityZ, float anglespeed,
                              float scale, int maxage, float red, float green, float blue, float alpha) {
        super(world, x, y, z, velocityX, velocityY, velocityZ);
        this.velocityX = velocityX;
        this.velocityY = velocityY;
        this.velocityZ = velocityZ;
        this.setAnglespeed(anglespeed);
        this.x = x;
        this.y = y;
        this.z = z;
        this.maxAge = maxage;
        this.setScale(scale);
        this.spriteProvider = spriteProvider;
        setSprite(spriteProvider);
        setColor(red, green, blue);
        setColorAlpha(alpha);
    }

    @Override
    public ParticleTextureSheet getType() {
        return ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT;
    }

    @Override
    public void move(double dx, double dy, double dz) {
        this.setBoundingBox(this.getBoundingBox().offset(dx, dy, dz));
        this.repositionFromBoundingBox();
    }

    //大小变化
    @Override
    public float getSize(float tickDelta) {
        return this.getScale();
    }

    //设置rgb三原色注意范围是0-1
    @Override
    public void setColor(float red, float green, float blue) {
        this.colorRed = red;
        this.colorGreen = green;
        this.colorBlue = blue;
    }

    //设置粒子的半透明度，注意范围是0-1，只有粒子在半透明情况下才有用，不透明时候无用。
    @Override
    public void setColorAlpha(float alpha) {
        this.colorAlpha = alpha;
    }

    public float getColorAlpha(float tint) {
        return this.colorAlpha;
    }

    //获取亮度，注意亮度只使用了int的16进制状态下的第二位和第六位例如最高亮度是0x00F000F0其中第二位是方块亮度，第六位是天空亮度
    @Override
    public int getBrightness(float tint) {
        return 0xF000F0;
    }

    //      闪烁
    //        float f = ((float) this.age + tint) / (float) this.maxAge;
    //        int count = 0;
    //        float n = 2, t = 1 / n;
    //        while (f >= t) {
    //            f -= t;
    //            count++;
    //        }
    //        if (count % 2 == 0) {
    //            int light = (int) (15 * f / t);
    //            return light << 4 | light << 20;
    //        } else {
    //            int light = (int) (15 * (1 - f / t));
    //            return light << 4 | light << 20;
    //        }
    //    从暗到亮
    //    float f = ((float) this.age + tint) / (float) this.maxAge;
    //    f = MathHelper.clamp(f, 0.0f, 1.0f) * 240;
    //    int i = (int) f;
    //    return i | i << 16;

    //渲染粒子
    @Override
    public void buildGeometry(VertexConsumer vertexConsumer, Camera camera, float tickDelta) {
        Quaternion quaternion;
        Vec3d vec3d = camera.getPos();
        float f = (float) (MathHelper.lerp(tickDelta, this.prevPosX, this.x) - vec3d.getX());
        float g = (float) (MathHelper.lerp(tickDelta, this.prevPosY, this.y) - vec3d.getY());
        float h = (float) (MathHelper.lerp(tickDelta, this.prevPosZ, this.z) - vec3d.getZ());
        if (this.angle == 0.0f) {
            quaternion = camera.getRotation();
        } else {
            quaternion = new Quaternion(camera.getRotation());
            float i = MathHelper.lerp(tickDelta, this.prevAngle, this.angle);
            quaternion.hamiltonProduct(Vec3f.POSITIVE_Z.getRadialQuaternion(i));
        }
        Vec3f vec3f = new Vec3f(-1.0f, -1.0f, 0.0f);
        vec3f.rotate(quaternion);
        Vec3f[] vec3fs = new Vec3f[]{new Vec3f(-1.0f, -1.0f, 0.0f), new Vec3f(-1.0f, 1.0f, 0.0f), new Vec3f(1.0f, 1.0f, 0.0f), new Vec3f(1.0f, -1.0f, 0.0f)};
        float j = this.getSize(tickDelta);
        for (int k = 0; k < 4; ++k) {
            Vec3f vec3f2 = vec3fs[k];
            vec3f2.rotate(quaternion);
            vec3f2.scale(j);
            vec3f2.add(f, g, h);
        }
        float l = this.getMinU();
        float m = this.getMaxU();
        float n = this.getMinV();
        float o = this.getMaxV();
        int p = this.getBrightness(tickDelta);
        float alpha = getColorAlpha(tickDelta);
        vertexConsumer.vertex(vec3fs[0].getX(), vec3fs[0].getY(), vec3fs[0].getZ()).texture(m, o).color(this.colorRed, this.colorGreen, this.colorBlue, alpha).light(p).next();
        vertexConsumer.vertex(vec3fs[1].getX(), vec3fs[1].getY(), vec3fs[1].getZ()).texture(m, n).color(this.colorRed, this.colorGreen, this.colorBlue, alpha).light(p).next();
        vertexConsumer.vertex(vec3fs[2].getX(), vec3fs[2].getY(), vec3fs[2].getZ()).texture(l, n).color(this.colorRed, this.colorGreen, this.colorBlue, alpha).light(p).next();
        vertexConsumer.vertex(vec3fs[3].getX(), vec3fs[3].getY(), vec3fs[3].getZ()).texture(l, o).color(this.colorRed, this.colorGreen, this.colorBlue, alpha).light(p).next();
    }

    //相对于相机所在轴的旋转速度
    public void tickangle() {
        this.prevAngle = this.angle;
        this.angle += this.getAnglespeed();
    }

    //每tick干的事情
    @Override
    public void tick() {
        this.prevPosX = this.x;
        this.prevPosY = this.y;
        this.prevPosZ = this.z;
        tickangle();
        if (this.age++ >= this.maxAge) {
            this.markDead();
            return;
        }
        this.move(this.velocityX, this.velocityY, this.velocityZ);
    }

    public float getAnglespeed() {
        return anglespeed;
    }

    public void setAnglespeed(float anglespeed) {
        this.anglespeed = anglespeed;
    }

    public float getScale() {
        return scale;
    }

    public void setScale(float scale) {
        this.scale = scale;
    }

    @Environment(value = EnvType.CLIENT)
    public static class Factory implements ParticleFactory<DefaultParticleType> {
        private final SpriteProvider spriteProvider;

        public Factory(SpriteProvider spriteProvider) {
            this.spriteProvider = spriteProvider;
        }

        @Override
        public Particle createParticle(DefaultParticleType defaultParticleType, ClientWorld clientWorld, double d, double e, double f, double g, double h, double i) {
            return new CustomBaseParticle(spriteProvider, clientWorld, d, e, f, g, h, i);
        }
    }
}
